﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net.Configuration;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using DevExpress.Spreadsheet;
using DevExpress.XtraBars.Docking2010.Views.WindowsUI;
using DevExpress.XtraPrinting.Native;
using DevExpress.XtraSpreadsheet;
using DevExpress.XtraSpreadsheet.Menu;
using EduFormManager.Models;
using EduFormManager.Models.Repo;
using EduFormManager.Properties;
using EduFormManager.Utilities;
using DocumentFormat = DevExpress.Spreadsheet.DocumentFormat;

namespace EduFormManager.Forms.UserControls.QueryControl
{
    public partial class XtraCreateQueryControl : XtraBaseControl, ISupportDocumentActions
    {
        private Allform _selectedForm;
        private XtraDictionaryEditQueryControl _editQueryControl;
        private Point _splitterLocation;
        private new IList<Query> _editedList;

        public IList<QueryPartAutocomplete> QueryPartAutocomleteSource
        {
            set { _editQueryControl.QueryPartAutocompleteSource = value; }
        }
        public IList<QueryPartHead> QueryPartHeadSource
        {
            set { _editQueryControl.QueryPartHeadSource = value; }
        }
        public XtraCreateQueryControl(WindowsUIView view)
            : base(view)
        {
            InitializeComponent();
            InitializeProps();
            _editedList = new List<Query>();
        }

        private void InitializeProps()
        {
            this.listBox1.DrawMode = DrawMode.OwnerDrawVariable;
            this.listBox1.MeasureItem += GuiUtility.lst_MeasureItem;
            this.listBox1.DrawItem += GuiUtility.lst_DrawItem;

            this.queryBindingSource.AllowNew = true;

            this.queryBindingSource.ListChanged += (s, e) => 
            {
                if (e.ListChangedType == ListChangedType.ItemChanged)
                {
                    Query query = this.queryBindingSource.Current as Query;
                    if (!_editedList.Contains(query))
                        _editedList.Add(query);
                }
            };
            _editQueryControl = this.flyoutPanel1.Controls.Find("xtraDictionaryEditQueryControl1", false).First() as XtraDictionaryEditQueryControl;
            _editQueryControl.QueriesCreated += async (s, e) =>
            {
                if (!e.Canceled)
                {
                    IList<Query> queryList = e.QueryList;
                    ProgressDialog.ShowTop(this.ParentForm, description: "Сохраняю");
                    await SaveQueries(queryList, false, true);
                    ProgressDialog.HideTop();
                    this.queryBindingSource.ResetBindings(false);
                    this.listBox1.ResetBindings();
                }
                this.flyoutPanel1.HidePopup();
            };
            _editQueryControl.CellAddressClicked += (s, e) =>
            {
                string cellAddress = e.Value;
                SetActiveWorksheetFromCell(cellAddress);
            };
            this.flyoutPanel1.Shown += (s, e) =>
            {
                _splitterLocation = this.splitterItem1.Location;
                _editQueryControl.Clear();
                this.splitterItem1.Location = new Point(_editQueryControl.Width - this.splitterItem1.Width, _splitterLocation.Y);
            };
            this.flyoutPanel1.Hidden += (s, e) =>
            {
                this.splitterItem1.Location = _splitterLocation;
            };
        }

        private void SetActiveWorksheetFromCell(string cellReference)
        {
            Regex worksheetRegex = new Regex(CheckExpressionRegexpConsts.EXP_PART_WORKSHEET_REGEXP);
            Match worksheetMatch = worksheetRegex.Match(cellReference);
            if (worksheetMatch.Success)
            {
                string worksheetName = worksheetMatch.Groups["Workbook"].Value;
                if (!String.IsNullOrEmpty(worksheetName))
                {
                    Worksheet worksheet = this.spreadsheetControlQueries.Document.Worksheets[worksheetName];
                    this.spreadsheetControlQueries.Document.Worksheets.ActiveWorksheet = worksheet;

                    Regex cellRegex = new Regex(CheckExpressionRegexpConsts.EXP_PART_CELL_REGEXP);
                    Match cellMatch = cellRegex.Match(cellReference);
                    if (cellMatch.Success)
                    {
                        string cellAddress = cellMatch.Groups["Cell"].Value;
                        if (!String.IsNullOrEmpty(cellAddress))
                        {
                            worksheet.SelectedCell = worksheet.Cells[cellAddress];
                        }}
                }
            }
        }

        private Task SaveQueries(IList<Query> queryList, bool clearSourceList = false, bool addToBindingSource = false)
        {
            return Task.Run(() =>
            {
                foreach (Query query in queryList)
                {
                    if (query.AllForm != null && !string.IsNullOrEmpty(query.Title) &&
                        !string.IsNullOrEmpty(query.Content))
                    {
                        query.Credentials = Authentication.CurrentCredentials;
                        RepoHelper.Repo.Save(query);
                        if (addToBindingSource) this.queryBindingSource.Add(query);
                    }
                }
                if (clearSourceList) queryList.Clear();
            });
        }

        public void Save()
        {
            Save(null);
        }

        async protected override void Save(Document doc)
        {
            if (!CanSave(doc))
            {
                this.ShowFlyoutMessageBox("Информация", "Не все поля заполнены", FlyoutCommand.OK);
                return;
            }
            ProgressDialog.ShowTop(this.ParentForm, description: "Сохраняю");
            await SaveQueries(_editedList, true, false);
            ProgressDialog.HideTop();
        }

        public bool CanSave()
        {
            return CanSave(null);
        }

        protected override bool CanSave(Document doc)
        {
            return queryBindingSource.Current != null && 
                this.comboBoxForm.SelectedItem != null && 
                !String.IsNullOrEmpty(textBoxCreateQueryName.Text) && 
                !String.IsNullOrEmpty(textBoxCreateQueryCell.Text);
        }

        public void New()
        {
            New(null);
        }

        protected override void New(Document doc)
        {
            _editQueryControl.SelectedForm = (this.comboBoxForm.SelectedItem as TemplatedFormData).AllForm;
            this.flyoutPanel1.ShowPopup();
        }

        public bool CanNew()
        {
            return CanNew(null);
        }

        protected override bool CanNew(Document doc)
        {
            return true;
        }

        public void Remove()
        {
            Remove(null);
        }

        public bool CanRemove()
        {
            return CanRemove(null);
        }

        protected override void Remove(Document doc)
        {
            if (!CanRemove(doc))
            {
                this.ShowFlyoutMessageBox("Ошибка", "Не выбран объект для удаления", FlyoutCommand.OK);
                return;
            }
            Query query = (Query)queryBindingSource.Current;
            RepoHelper.Repo.Delete(query);
            queryBindingSource.Remove(query);
            queryBindingSource.EndEdit();
        }

        protected override bool CanRemove(Document doc)
        {
            return queryBindingSource.Current != null;
        }

        private void spreadsheetControlQueries_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e)
        {
            if (e.MenuType == SpreadsheetMenuType.Cell)
            {
                e.Menu.Items.Clear();
                SpreadsheetMenuItem i = new SpreadsheetMenuItem("Использовать в запросе", (o, args) =>
                {
                    string cellAddress = spreadsheetControlQueries.ActiveWorksheet.SelectedCell.GetReferenceA1(ReferenceElement.IncludeSheetName | ReferenceElement.RowAbsolute | ReferenceElement.ColumnAbsolute);
                    if (this.flyoutPanel1.IsPopupOpen)
                    {
                        _editQueryControl.SetCellAddressToCurrentQuery(cellAddress);
                    }
                    else
                    {
                        Query query = this.queryBindingSource.Current as Query;
                        if (query != null)
                        {
                            textBoxCreateQueryCell.Text = cellAddress;
                            query.Content = cellAddress;
                            if (!_editedList.Contains(query))
                                _editedList.Add(query);
                        }
                    }
                });
                e.Menu.Items.Add(i);
            }
        }

        async private void comboBoxCreateQueryForm_SelectedIndexChanged(object sender, EventArgs e)
        {
            ComboBox combo = sender as ComboBox;
            TemplatedFormData template = combo.SelectedItem as TemplatedFormData;
            if (template == null)
            {
                return;
            }
            byte[] excelData = template.ExcelFileBytes;
            using (MemoryStream ms = new MemoryStream(excelData))
            {
                DocumentFormat format = DocumentFormat.OpenXml;
                this.spreadsheetControlQueries.LoadDocument(ms, format);
            }
            _selectedForm = template.AllForm;

            this.Enabled = false;
            IList<Query> queries = await RepoHelper.Repo.GetQueriesByFormAsync(template.AllForm, Authentication.CurrentCredentials);
            queryBindingSource.DataSource = queries;
            this.Enabled = true;
        }

        public void OnQueryDocumentActions(IDocumentActionsArgs args)
        {
            args.DocumentActions.Add(new DocumentAction(New) { Caption = "Создать", Image = Resources.glyphicons_432_plus });
            args.DocumentActions.Add(new DocumentAction(Save) { Caption = "Сохранить", Image = Resources.glyphicons_206_ok_2 });
            args.DocumentActions.Add(new DocumentAction(Remove) { Caption = "Удалить", Image = Resources.glyphicons_207_remove_2 });
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            Query query = this.listBox1.SelectedItem as Query;
            if (query != null)
            {
                string cellAddress = query.Content;
                SetActiveWorksheetFromCell(cellAddress);
            }
        }

        
    }
}
